<?php

namespace App\Libraries\AppSocialite\Providers;

use App\Libraries\AppSocialite\Exceptions\TokenInvalidException;
use App\Libraries\AppSocialite\User;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class WeChatProvider extends AbstractProvider
{
    /**
     * Get WeChat OAuth2 access token.
     *
     * @param string $code
     *
     * @return  array
     */
    protected function getAccessTokenResponse(string $code): array
    {
        return Http::get('https://api.weixin.qq.com/sns/oauth2/access_token', [
            'appid' => $this->config['appid'],
            'secret' => $this->config['appsecret'],
            'code' => $code,
            'grant_type' => 'authorization_code',
        ])->json();
    }

    /**
     *  Get the raw user for the given access token.
     *
     * @param string $token
     *
     * @return \Illuminate\Http\Client\Response
     * @throws TokenInvalidException
     */
    protected function getUserByToken($token)
    {
        $token = $this->getAccessTokenResponse($token);
        Log::channel('oauth')->debug($token);
        if (empty($token['access_token'] ?? null) || empty($token['openid'])) {
            throw new TokenInvalidException('Access Token 获取失败');
        }

        return Http::get('https://api.weixin.qq.com/sns/userinfo', [
            'access_token' => $token['access_token'],
            'openid' => $token['openid'],
            'lang' => 'zh_CN',
        ]);
    }

    /**
     * Get the User instance for the authenticated user.
     *
     * @return \App\Libraries\AppSocialite\Contracts\User
     * @throws TokenInvalidException
     */
    public function user()
    {
        $response = $this->getUserByToken($this->request['code']);
        $user = json_decode($response->body(), true);

        return $this->mapUserToObject($user);
    }

    /**
     * {@inheritdoc}
     */
    protected function mapUserToObject(array $user)
    {
        return (new User())->setRaw($user)
            ->map([
                // HACK: use openid as user id
                'id' => $user['openid'],
                'name' => isset($user['nickname']) ? $user['nickname'] : null,
                'avatar' => $user['headimgurl'] ?? '',
                'gender' => $user['sex'] ?? '0'
            ]);
    }
}
